﻿using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Lime49.UI;
using LockCrypt.Core;
using LockCrypt.DAL;
using LockCrypt.Properties;

namespace LockCrypt {
    /// <summary>
    /// Dialog for opening databases.
    /// </summary>
    public partial class WinOpenDatabase : Window {
        public enum FileImportAction {
            Open,
            Merge
        }
        public FileImportAction OpenAction { get; set; }

        public IDbProvider Provider {
            get { return dbSelector.Provider; }
        }

        /// <summary>
        /// Initializes a new <see cref="WinOpenDatabase"/>.
        /// </summary>
        public WinOpenDatabase() {
            InitializeComponent();
        }

        /// <summary>
        /// Initializes a new <see cref="WinOpenDatabase"/>.
        /// </summary>
        /// <param name="type">The database type to pre-select.</param>
        /// <param name="encryption">The encryption algorithm to pre-select.</param>
        public WinOpenDatabase(Constants.DatabaseType type, EncryptionProviders encryption)
            : this(string.Empty, type, encryption) {
        }

        /// <summary>
        /// Initializes a new <see cref="WinOpenDatabase"/>.
        /// </summary>
        /// <param name="fileName">Name of the file to open.</param>
        /// <param name="type">The database type to pre-select.</param>
        /// <param name="encryption">The encryption algorithm to pre-select.</param>
        public WinOpenDatabase(string fileName, Constants.DatabaseType type, EncryptionProviders encryption) 
            :this() {
            dbSelector.DatabasePath = fileName;
            dbSelector.DatabaseMode = type;
            dbSelector.EncryptionAlgorithm = encryption;
        }

        /// <summary>
        /// Validates the credentials entered.
        /// </summary>
        /// <returns><c>true</c> if the credentials are valid, otherwise <c>false</c>.</returns>
        private bool ValidateDatabase() {
            bool valid = true;
            if(!dbSelector.ValidateSettings()) {
                valid = false;
            } else {
                BackgroundWorker worker = new BackgroundWorker();
                IDbProvider newProvider = this.Provider;
                worker.DoWork += (s, dwe) => {
                    dwe.Result = newProvider.CheckPassword();
                };
                worker.RunWorkerCompleted += (s, rwe) => {
                    if(rwe.Error != null) {
                        DialogBox.ShowAlert(this, rwe.Error.Message, I18nUtils.GetString("Errors", "Error"));
                        valid = false;
                    } else if(!Convert.ToBoolean(rwe.Result)) {
                        DialogBox.ShowAlert(this, I18nUtils.GetString("Errors", "IncorrectPassword"), I18nUtils.GetString("Errors", "Error")); 
                        valid = false;
                        /*correctPassword = Convert.ToBoolean(rwe.Result);
                        if(!correctPassword) {
                            // check if current pass is valid
                            WinPromptPassword dlg = new WinPromptPassword(provider) { Owner = this };
                            correctPassword = dlg.ShowDialog() == true;
                            modifiedProvider = dlg.DatabaseProvider;
                        }*/
                    }
                };
                worker.RunWorkerAsync();
                while(worker.IsBusy) {
                    Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate() { }));
                }
            }
            return valid;
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void CloseWindow(object sender, ExecutedRoutedEventArgs e) {
            DialogResult = false;
        }

        /// <summary>
        /// Tries to open the specified database.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void OpenDatabase(object sender, ExecutedRoutedEventArgs e) {
            if(ValidateDatabase()) {
                Settings.Default.Save();
                this.OpenAction = (FileImportAction)Enum.Parse(typeof(FileImportAction), (e.Parameter ?? "open").ToString(), true);
                DialogResult = true;
            }
        }
    }
}
